/**
 * BaseController.java 
 * Copyright © 2015-3015, 杭州泊享网络科技有限公司
 * 
 * @author Liu Tao
 * @create 2013年8月16日
 */
package com.pshare.framework.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.pshare.base.bean.SeaxResponse;
import com.pshare.constant.ResponseCode;
import com.pshare.constant.ReturnCode;
import com.pshare.constant.SeaxConstants;
import com.pshare.enums.CodeMsg;
import com.pshare.framework.exception.NoAuthException;
import com.pshare.framework.exception.NoLoginException;
import com.pshare.framework.exception.NoPermissionException;
import com.pshare.framework.exception.SeaxRuntimeException;
import com.pshare.framework.exception.WrongParamException;
import com.pshare.framework.service.FileUploadService;
import com.pshare.util.SysPropertyUtils;

/**
 * 控制接口层基础父类
 */
@Controller
public class BaseController {

	protected static final Integer MAX_PIC_COUNT = Integer.parseInt(SysPropertyUtils.getProperty("pic.max.count"));

	protected static final String TEMPLATE = SeaxConstants.KEY_VIEW_NAME;

	protected static final Logger logger = Logger.getLogger(BaseController.class);

	@Autowired
	private FileUploadService fileUploadService;

	public static SeaxResponse getResult(boolean status, String message) {
		return getResponseData(status, null, message);
	}

	public static SeaxResponse getResult(boolean status, Object res, String message) {
		return getResponseData(status, res, message);
	}

	public static SeaxResponse getResult(boolean status, List<FieldError> errors) {
		return getResponseData(status, null, ReturnCode.WRONG_PARAM, null, errors);
	}

	private static SeaxResponse getResponseData(boolean status, Object res, String message) {
		return getResponseData(status, res, message, null);
	}

	private static SeaxResponse getResponseData(boolean status, Object res, String message, List<FieldError> errors) {
		if (status) {
			return getResponseData(status, res, message, errors, ReturnCode.SUCCESS);
		} else {
			return getResponseData(status, res, message, errors, ReturnCode.BIZ_ERROR);
		}
	}

	private static SeaxResponse getResponseData(boolean status, Object res, Integer code, String message,
			List<FieldError> errors) {
		return getResponseData(status, res, message, errors, code);
	}

	protected SeaxResponse succeed() {
		return succeed(SeaxConstants.EMPTY);
	}
	
	protected SeaxResponse succeed(String message) {
		return getResult(true, null, message);
	}

	protected SeaxResponse succeed(Object object) {
		return succeed(SeaxConstants.EMPTY, object);
	}

	protected SeaxResponse succeed(String message, Object object) {
		return getResult(true, object, message);
	}

	protected SeaxResponse failed() {
		return getResult(false, SeaxConstants.EMPTY);
	}

//	protected SeaxResponse failed(String message) {
//		return getResult(false, message);
//	}

	protected SeaxResponse failed(Integer code) {
		String message = CodeMsg.getMsg(code, isEN());
		return getResult(false, message, code);
	}

	protected SeaxResponse failed(String message, Integer code) {
		return getResult(false, message, code);
	}

	/**
	 * @param status
	 * @param message
	 * @param code
	 * @return SeaxResponse
	 */
	private static SeaxResponse getResult(boolean status, String message, Integer code) {
		return getResponseData(status, null, message, null, code);
	}

	/**
	 * @param status
	 * @param res
	 * @param message 异常消息
	 * @param code 异常代码编号
	 * @return SeaxResponse
	 */
	private static SeaxResponse getResponseData(boolean status, Object data, String message, List<FieldError> errors,
			Integer code) {
		SeaxResponse obj = new SeaxResponse();
		obj.setStatus(status);
		obj.setData(data);
		obj.setCode(code);
		obj.setMsg(message);
		if (errors != null) {
			for (FieldError error : errors) {
				if (SeaxConstants.KEY_SIGN_DATA.equalsIgnoreCase(error.getField())) {
					obj.setCode(CodeMsg.WRONG_SIGN.getCode());
				} else {
					obj.addError(error);
				}
			}
		}
		return obj;
	}

	protected SeaxResponse failed(List<FieldError> errors) {
		logger.error("-------------------------------------");
		for (FieldError err : errors) {
			logger.error(err.getField() + ":" + err.getArguments() + ":" + err.getDefaultMessage() + ":" + err.getCode());
		}
		logger.error("-------------------------------------");
		
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		response.setStatus(ResponseCode.BAD_REQUEST);
		return getResult(false, errors);
	}

	protected SeaxResponse failed(boolean status, String message) {
		return getResult(status, message);
	}

	protected String getErrorsMessage(BindingResult result) {
		String message = "";
		List<ObjectError> list = result.getAllErrors();
		for (ObjectError objectError : list) {
			message = message + objectError.getDefaultMessage() + ";";
		}
		return message;
	}

	/**
	 * 处理一般异常
	 * 
	 * @param ex
	 * @return SeaxResponse
	 */
	@ExceptionHandler(Exception.class)
	@ResponseBody
	public SeaxResponse handleException(HttpServletRequest request, HttpServletResponse response, Exception ex) {
		logger.error(ex.getMessage(), ex);
		if (ex instanceof NoAuthException) {
			response.setStatus(ResponseCode.UNAUTHORIZED);
			return failed(((NoAuthException) ex).getCode());
		} else if (ex instanceof org.springframework.web.multipart.MaxUploadSizeExceededException) {
			response.setStatus(ResponseCode.REQ_ENTITY_TOO_LARGE);
			return failed(ReturnCode.REQ_ENTITY_TOO_LARGE);
		} else if (ex instanceof org.springframework.web.HttpMediaTypeNotSupportedException) {
			response.setStatus(ResponseCode.UNSUPPORTMEDIATYPE);
			return failed(CodeMsg.UNSUPPORTMEDIATYPE.getCode());
		} else if (ex instanceof org.springframework.http.converter.HttpMessageNotReadableException) {
			response.setStatus(ResponseCode.BAD_REQUEST);
			return failed(ReturnCode.BAD_REQUEST);
		} else if (ex instanceof WrongParamException) {
			response.setStatus(ResponseCode.BAD_REQUEST);
			return failed(((WrongParamException) ex).getCode());
		} else if (ex instanceof NoLoginException) {
			response.setStatus(ResponseCode.UNAUTHORIZED);
			return failed(((NoLoginException) ex).getCode());
		} else if (ex instanceof NoPermissionException) {
			response.setStatus(ResponseCode.UNAUTHORIZED);
			return failed(((NoPermissionException) ex).getCode());
		} else if (ex instanceof SeaxRuntimeException) {
			SeaxRuntimeException srException = (SeaxRuntimeException) ex;
			logger.error(srException.getMsg(isEN()), ex);
			return failed(srException.getMessage(), srException.getCode());
		} else {
			return failed(ReturnCode.SYSTEM_ERROR);
		}
	}

	/**
	 * 处理自定义运行时异常
	 * 
	 * @param ex
	 * @param request
	 * @return
	 */
	@ExceptionHandler(SeaxRuntimeException.class)
	@ResponseBody
	public SeaxResponse handleException(SeaxRuntimeException ex, HttpServletRequest request) {
		logger.error(ex.getMsg(isEN()), ex);
		return failed(ex.getCode());
	}

	@ExceptionHandler(MethodArgumentNotValidException.class)
	@ResponseBody
	public SeaxResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
		logger.error(ex.getMessage(), ex);
		BindingResult bindingResult = ex.getBindingResult();
		String errorMesssage = "";

		for (FieldError fieldError : bindingResult.getFieldErrors()) {
			errorMesssage += fieldError.getDefaultMessage() + ", ";
		}

		return failed(errorMesssage, CodeMsg.SYSTEM_ERROR.getCode());
	}

	protected List<String> uploadMultiPictures(MultipartHttpServletRequest request, HttpServletResponse response,
			int oldCount) {
		List<String> photoUrls = new ArrayList<String>();
		boolean isEN = isEN(request);
		// 上传图片
		try {
			// Map files = request.getFileMap();
			Map files = request.getMultiFileMap();
			if (files.size() == 0) {
				return photoUrls;
			} else if (files.size() + oldCount > MAX_PIC_COUNT) {
				throw new SeaxRuntimeException(isEN ? "Please upload " + MAX_PIC_COUNT + " files at one time."
						: "一次最多只能上传" + MAX_PIC_COUNT + "张图片");
			}
			for (Iterator<String> iter = request.getFileNames(); iter.hasNext();) {
				LinkedList list = (LinkedList) files.get(iter.next());
				CommonsMultipartFile file = (CommonsMultipartFile) list.getFirst();
				if (file == null) {
					continue;
				}

				String url = fileUploadService.uploadPictureToUpYun(file);
				if (StringUtils.isNotBlank(url)) {
					photoUrls.add(url);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new SeaxRuntimeException(e.getMessage());
		}
		return photoUrls;
	}

	protected void checkParam() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		Map<String, String[]> params = request.getParameterMap();
		for (String key : params.keySet()) {

		}
	}

	/**
	 * 读取客户端IP地址
	 * 
	 * @param request
	 * @return String
	 */
	protected String getRemoteAddr(HttpServletRequest request) {
		if (request.getHeader("x-forwarded-for") == null) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for");
	}

	/**
	 * 判断客户端是否是英文环境
	 * 
	 * @param request
	 * @return boolean
	 */
	protected static boolean isEN(HttpServletRequest request) {
		boolean isEN = false;
		String language = request.getHeader("Accept-Language");
		if (language == null || language.toUpperCase().startsWith(SeaxConstants.ACCEPT_LANGUAGE_ZH)) { // 如果是空，或中文
			logger.info("LANGUAGE:CN");
		} else { // 其他统一用英文处理
			logger.info("LANGUAGE:EN");
			isEN = true;
		}
		return isEN;
	}

	/**
	 * 判断客户端是否是英文环境
	 * 
	 * @return boolean
	 */
	protected static boolean isEN() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		return isEN(request);
	}

	

}
